package com.fingard.dsp.bank.directbank.gzelink01;

import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.gzelink01.util.Md5;
import com.fingard.dsp.bank.directbank.gzelink01.util.MySSLProtocolSocketFactory;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.gnete.security.crypt.Crypt;
import com.gnete.security.crypt.CryptException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class GZELINK01Base extends DirectBase {

    private static TransIDHelper idHelper = new TransIDHelper(1, 999);

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    public String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    public String getCharset(String p_for) {
        return getBankConfig().getCharset("GBK", p_for);
    }

    protected StringBuilder writeCommonHeader(StringBuilder p_reqMsg, ActSetItem actItem, GZELINK01Header bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        p_reqMsg.append("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        p_reqMsg.append("<GZELINK>");
        p_reqMsg.append("<INFO>");
        p_reqMsg.append("<TRX_CODE>" + bankHeader.transCode + "</TRX_CODE>");
        p_reqMsg.append("<VERSION>03</VERSION>");
        p_reqMsg.append("<DATA_TYPE>2</DATA_TYPE>");
        p_reqMsg.append("<LEVEL>5</LEVEL>");
        p_reqMsg.append("<USER_NAME>" + actItem.userCode + "</USER_NAME>");
        p_reqMsg.append("<USER_PASS>" + actItem.userFlag + "</USER_PASS>");
        p_reqMsg.append("<REQ_SN>" + bankHeader.reqSeqNo + "</REQ_SN>");
        p_reqMsg.append("<SIGNED_MSG></SIGNED_MSG>");
        p_reqMsg.append("</INFO>");
        p_reqMsg.append("<BODY>");
        p_reqMsg.append("<TRANS_SUM>");

        return p_reqMsg;
    }

    protected StringBuilder write7516CommonHeader(StringBuilder p_reqMsg, ActSetItem actItem, GZELINK01Header bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        p_reqMsg.append("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        p_reqMsg.append("<GZELINK>");
        p_reqMsg.append("<INFO>");
        p_reqMsg.append("<TRX_CODE>" + bankHeader.transCode + "</TRX_CODE>");
        String version = getBankConfig().getValueAsString("trans7516Version");
        if ("06".equals(version)) {
            p_reqMsg.append("<VERSION>06</VERSION>");
        } else {
            p_reqMsg.append("<VERSION>03</VERSION>");
        }
        p_reqMsg.append("<DATA_TYPE>2</DATA_TYPE>");
        p_reqMsg.append("<LEVEL>5</LEVEL>");
        p_reqMsg.append("<USER_NAME>" + actItem.userCode + "</USER_NAME>");
        p_reqMsg.append("<USER_PASS>" + actItem.userFlag + "</USER_PASS>");
        p_reqMsg.append("<REQ_SN>" + bankHeader.reqSeqNo + "</REQ_SN>");
        p_reqMsg.append("<SIGNED_MSG></SIGNED_MSG>");
        p_reqMsg.append("</INFO>");
        p_reqMsg.append("<BODY>");

        return p_reqMsg;
    }


    protected StringBuilder writePayRecSubmitMsg(StringBuilder p_reqMsg, ActSetItem actItem, GZELINK01Header bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.busiCode)) {
            throw new Exception("busiCode未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.totalNum)) {
            throw new Exception("totalNum未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.totalAmt)) {
            throw new Exception("totalAmt未初始化");
        }

        p_reqMsg.append("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        p_reqMsg.append("<GZELINK>");

        p_reqMsg.append("<INFO>");
        p_reqMsg.append("<TRX_CODE>" + bankHeader.transCode + "</TRX_CODE>");
        p_reqMsg.append("<VERSION>05</VERSION>");
        p_reqMsg.append("<DATA_TYPE>2</DATA_TYPE>");
        p_reqMsg.append("<LEVEL></LEVEL>");
        p_reqMsg.append("<USER_NAME>" + actItem.userCode + "</USER_NAME>");
        p_reqMsg.append("<USER_PASS>" + actItem.userFlag + "</USER_PASS>");
        p_reqMsg.append("<REQ_SN>" + bankHeader.reqSeqNo + "</REQ_SN>");
        p_reqMsg.append("<SIGNED_MSG></SIGNED_MSG>");
        p_reqMsg.append("</INFO>");

        p_reqMsg.append("<BODY>");

        p_reqMsg.append("<TRANS_SUM>");
        p_reqMsg.append("<BUSINESS_CODE>" + bankHeader.busiCode + "</BUSINESS_CODE>");
        p_reqMsg.append("<MERCHANT_ID>" + actItem.merchantId + "</MERCHANT_ID>");
        p_reqMsg.append("<SUBMIT_TIME>" + Format.DateTime14Format.format(new Date()) + "</SUBMIT_TIME>");
        p_reqMsg.append("<TOTAL_ITEM>" + bankHeader.totalNum + "</TOTAL_ITEM>");
        p_reqMsg.append("<TOTAL_SUM>" + StringHelper.amountMultiply100(bankHeader.totalAmt) + "</TOTAL_SUM>");
        p_reqMsg.append("</TRANS_SUM>");

        p_reqMsg.append("<TRANS_DETAILS>");

        return p_reqMsg;
    }

    protected StringBuilder writeBatPayRecSubmitMsg(StringBuilder p_reqMsg, ActSetItem actItem, GZELINK01Header bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.busiCode)) {
            throw new Exception("busiCode未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.totalNum)) {
            throw new Exception("totalNum未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.totalAmt)) {
            throw new Exception("totalAmt未初始化");
        }

        p_reqMsg.append("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        p_reqMsg.append("<GZELINK>");

        p_reqMsg.append("<INFO>");
        p_reqMsg.append("<TRX_CODE>" + bankHeader.transCode + "</TRX_CODE>");
        p_reqMsg.append("<VERSION>05</VERSION>");
        p_reqMsg.append("<DATA_TYPE>2</DATA_TYPE>");
        p_reqMsg.append("<LEVEL></LEVEL>");
        p_reqMsg.append("<USER_NAME>" + actItem.userCode + "</USER_NAME>");
        p_reqMsg.append("<USER_PASS>" + actItem.userFlag + "</USER_PASS>");
        p_reqMsg.append("<REQ_SN>" + bankHeader.reqSeqNo + "</REQ_SN>");
        p_reqMsg.append("<SIGNED_MSG></SIGNED_MSG>");
        p_reqMsg.append("</INFO>");

        p_reqMsg.append("<BODY>");

        p_reqMsg.append("<TRANS_SUM>");
        p_reqMsg.append("<BUSINESS_CODE>" + bankHeader.busiCode + "</BUSINESS_CODE>");
        p_reqMsg.append("<MERCHANT_ID>" + actItem.merchantId + "</MERCHANT_ID>");
        p_reqMsg.append("<EXPECT_SEND_TIME></EXPECT_SEND_TIME>");
        p_reqMsg.append("<TOTAL_ITEM>" + bankHeader.totalNum + "</TOTAL_ITEM>");
        p_reqMsg.append("<TOTAL_SUM>" + StringHelper.amountMultiply100(bankHeader.totalAmt) + "</TOTAL_SUM>");
        p_reqMsg.append("</TRANS_SUM>");

        p_reqMsg.append("<TRANS_DETAILS>");

        return p_reqMsg;
    }

    protected StringBuilder writePayRecQueryMsg(StringBuilder p_reqMsg, ActSetItem actItem, GZELINK01Header bankHeader, String p_reqSN) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }

        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        p_reqMsg.append("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        p_reqMsg.append("<GZELINK>");

        p_reqMsg.append("<INFO>");
        p_reqMsg.append("<TRX_CODE>" + bankHeader.transCode + "</TRX_CODE>");
        p_reqMsg.append("<VERSION>05</VERSION>");
        p_reqMsg.append("<DATA_TYPE>2</DATA_TYPE>");
        p_reqMsg.append("<REQ_SN>" + p_reqSN + "</REQ_SN>");
        p_reqMsg.append("<USER_NAME>" + actItem.userCode + "</USER_NAME>");
        p_reqMsg.append("<USER_PASS>" + actItem.userFlag + "</USER_PASS>");
        p_reqMsg.append("<SIGNED_MSG></SIGNED_MSG>");
        p_reqMsg.append("</INFO>");

        p_reqMsg.append("<BODY>");

        p_reqMsg.append("<QUERY_TRANS>");
        p_reqMsg.append("<QUERY_SN>" + bankHeader.reqSeqNo + "</QUERY_SN>");
        p_reqMsg.append("<QUERY_REMARK></QUERY_REMARK>");
        p_reqMsg.append("<RET_TYPE></RET_TYPE>");
        p_reqMsg.append("</QUERY_TRANS>");

        p_reqMsg.append("<QUERY_DETAILS>");
        p_reqMsg.append("<QUERY_DETAIL>");
        p_reqMsg.append("<QUERY_DETAIL_SN></QUERY_DETAIL_SN>");
        p_reqMsg.append("</QUERY_DETAIL>");
        p_reqMsg.append("</QUERY_DETAILS>");

        p_reqMsg.append("</BODY>");
        p_reqMsg.append("</GZELINK>");

        return p_reqMsg;
    }

    protected String signMsg(String signData, ActSetItem actItem) {
        String signStr = "";

        try {
            signStr = new Crypt(getCharset()).sign(signData, actItem.ownKeyStorePath, actItem.ownKeyPassword);
        } catch (CryptException e) {
            e.printStackTrace();

            WriteBankLogLn2("签名失败，原因如下:\r\n" + LogHelper.getStackTrace(e));
        }

        return signStr;
    }

    protected boolean verifyNotifyAsyn(String signPlain, String signMsg, ActSetItem actItem) {
        String encodePKey = Md5.md5(actItem.saltKey, "UTF-8");
        signPlain += encodePKey;
        String encodeMsg = Md5.md5(signPlain, "UTF-8");

        //校验签名是否一致
        if (signMsg.equals(encodeMsg)) {
            return true;
        }

        return false;
    }

    protected String getReqPostData(NameValuePair[] params) {
        StringBuilder postData = new StringBuilder();

        for (NameValuePair param : params) {
            if (postData.length() > 0) {
                postData.append("&");
            }
            postData = postData.append(param.getName()).append("=").append(param.getValue());
        }

        return postData.toString();
    }

    protected Map<String, String> getRespPostData(String p_respStr) {
        Map<String, String> respData = new HashMap<String, String>();

        String[] respArrays = p_respStr.split("&");
        for (String respArray : respArrays) {
            int index = respArray.indexOf("=");
            String key = respArray.substring(0, index);
            String value = respArray.substring(index + 1);

            respData.put(key, value);
        }

        return respData;
    }

    protected String getContentType(String p_reqStr) {
        String respStr = "";

        int index = p_reqStr.indexOf("com/");
        respStr = p_reqStr.substring(0, index + 4);

        return respStr;
    }

    protected String[] sendDataToBank(String reqData) {
        String[] tmpRetStr = new String[]{"", ""};
        WriteBankLogStep2(reqData);

        String submitURL = bankFront.getUrl("qryRealtimeRecStatement") + "?" + reqData;
        WriteBankLogLn2("服务地址:" + submitURL);

        WebRequest tmpRequest = new WebRequest(submitURL);
        tmpRequest.setConnectTimeout(100000);
        tmpRetStr = tmpRequest.upload(null, getCharset());

        return tmpRetStr;
    }

    protected String[] sendDataToGZE(String p_reqData, String p_url) throws Exception {
        String[] tmpRetStr = new String[]{"", ""};

        WriteBankLogLn2("服务地址:" + p_url);
        WebRequest tmpRequest = new WebRequest(p_url);
        tmpRequest.setConnectTimeout(100000);

        byte[] tmpWriteBytes = p_reqData.getBytes(getCharset());
        tmpRetStr = tmpRequest.upload(tmpWriteBytes, getCharset());

        return tmpRetStr;
    }

    protected String sendAuthToBank(NameValuePair[] param, String p_for) throws Exception {
        String tmpRetStr = "";

        WriteBankLogLn2("服务地址: " + bankFront.getUrl(p_for));

        Protocol myhttps = new Protocol("https", new MySSLProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", myhttps);
        PostMethod post = new PostMethod(bankFront.getUrl(p_for));
        post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        post.setRequestBody(param);
        @SuppressWarnings("unused")
        int status = new HttpClient().executeMethod(post);

        InputStream responseBody = post.getResponseBodyAsStream();
        InputStreamReader in = new InputStreamReader(responseBody, "UTF-8");
        BufferedReader br = new BufferedReader(in);
        StringBuffer rets = new StringBuffer();
        String inputLine = "";
        while (null != (inputLine = br.readLine())) {
            rets.append(inputLine);
        }
        in.close();

        tmpRetStr = rets.toString().trim();
        WriteBankLogStep3(tmpRetStr);

        return tmpRetStr;
    }

}
